package org.csu.onlineedubackend.service.impl;

import org.csu.onlineedubackend.entity.ChatGroup;
import org.csu.onlineedubackend.entity.GroupAdmin;
import org.csu.onlineedubackend.entity.GroupMute;
import org.csu.onlineedubackend.entity.User;
import org.csu.onlineedubackend.entity.ChatMessage;
import org.csu.onlineedubackend.entity.Notification;
import org.csu.onlineedubackend.mapper.*;
import org.csu.onlineedubackend.service.GroupManagementService;
import org.csu.onlineedubackend.service.NotificationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.csu.onlineedubackend.websocket.ChatWebSocketHandler;

import java.util.*;

@Service
public class GroupManagementServiceImpl implements GroupManagementService {

    @Autowired
    private ChatGroupMapper chatGroupMapper;
    
    @Autowired
    private GroupAdminMapper groupAdminMapper;
    
    @Autowired
    private GroupMuteMapper groupMuteMapper;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private ConversationParticipantMapper participantMapper;
    
    @Autowired
    private ConversationMapper conversationMapper;
    
    @Autowired
    private MessageMapper messageMapper;
    
    @Autowired
    private ChatWebSocketHandler chatWebSocketHandler;
    
    @Autowired
    private NotificationService notificationService;
    
    @Override
    @Transactional
    public GroupAdmin setGroupAdmin(Long groupId, Integer userId, Integer operatorId) {
        // 检查操作者是否是群主
        ChatGroup chatGroup = chatGroupMapper.findById(groupId);
        if (chatGroup == null) {
            throw new RuntimeException("群组不存在");
        }
        
        if (!chatGroup.getOwnerId().equals(operatorId)) {
            throw new RuntimeException("只有群主可以设置管理员");
        }
        
        // 检查被设置者是否是群成员
        List<User> participants = participantMapper.findParticipantsByConversationId(chatGroup.getConversationId());
        boolean isMember = participants.stream().anyMatch(p -> p.getId().equals(userId));
        if (!isMember) {
            throw new RuntimeException("该用户不是群成员");
        }
        
        // 检查是否已经是管理员
        if (groupAdminMapper.isGroupAdmin(groupId, userId)) {
            throw new RuntimeException("该用户已经是管理员");
        }
        
        // 设置为管理员
        GroupAdmin groupAdmin = new GroupAdmin();
        groupAdmin.setGroupId(groupId);
        groupAdmin.setUserId(userId);
        groupAdminMapper.insert(groupAdmin);
        
        // 获取用户信息
        User user = userMapper.findById(userId);
        groupAdmin.setUser(user);
        
        // 创建通知
        Notification notification = new Notification();
        notification.setUserId(userId);
        notification.setType("GROUP_ADMIN_ADDED");
        notification.setGroupId(groupId);
        notification.setGroupName(chatGroup.getName());
        notification.setTitle("群管理员通知");
        notification.setContent("恭喜！您在群聊 " + chatGroup.getName() + " 中被设为管理员");
        notification.setIsRead(false);
        notification.setCreatedAt(new Date());
        
        notificationService.addNotification(notification);
        
        return groupAdmin;
    }
    
    @Override
    @Transactional
    public boolean removeGroupAdmin(Long groupId, Integer userId, Integer operatorId) {
        // 检查操作者是否是群主
        ChatGroup chatGroup = chatGroupMapper.findById(groupId);
        if (chatGroup == null) {
            throw new RuntimeException("群组不存在");
        }
        
        if (!chatGroup.getOwnerId().equals(operatorId)) {
            throw new RuntimeException("只有群主可以取消管理员");
        }
        
        // 检查是否是管理员
        if (!groupAdminMapper.isGroupAdmin(groupId, userId)) {
            throw new RuntimeException("该用户不是管理员");
        }
        
        // 取消管理员
        boolean result = groupAdminMapper.deleteByGroupAndUser(groupId, userId) > 0;
        
        if (result) {
            // 创建通知
            Notification notification = new Notification();
            notification.setUserId(userId);
            notification.setType("GROUP_ADMIN_REMOVED");
            notification.setGroupId(groupId);
            notification.setGroupName(chatGroup.getName());
            notification.setTitle("群管理员通知");
            notification.setContent("您在群聊 " + chatGroup.getName() + " 中被取消管理员身份");
            notification.setIsRead(false);
            notification.setCreatedAt(new Date());
            
            notificationService.addNotification(notification);
        }
        
        return result;
    }
    
    @Override
    public List<User> getGroupAdmins(Long groupId) {
        return groupAdminMapper.findAdminsByGroupId(groupId);
    }
    
    @Override
    public boolean isGroupAdmin(Long groupId, Integer userId) {
        return groupAdminMapper.isGroupAdmin(groupId, userId);
    }
    
    @Override
    public boolean isGroupOwner(Long groupId, Integer userId) {
        ChatGroup chatGroup = chatGroupMapper.findById(groupId);
        return chatGroup != null && chatGroup.getOwnerId().equals(userId);
    }
    
    @Override
    @Transactional
    public GroupMute muteGroupMember(Long groupId, Integer userId, Integer operatorId, Date muteUntil) {
        // 检查操作者权限
        ChatGroup chatGroup = chatGroupMapper.findById(groupId);
        if (chatGroup == null) {
            throw new RuntimeException("群组不存在");
        }
        
        boolean isOwner = chatGroup.getOwnerId().equals(operatorId);
        boolean isAdmin = groupAdminMapper.isGroupAdmin(groupId, operatorId);
        
        if (!isOwner && !isAdmin) {
            throw new RuntimeException("只有群主或管理员可以禁言成员");
        }
        
        // 检查被禁言者是否是群主或管理员
        if (chatGroup.getOwnerId().equals(userId)) {
            throw new RuntimeException("不能禁言群主");
        }
        
        if (groupAdminMapper.isGroupAdmin(groupId, userId) && !isOwner) {
            throw new RuntimeException("管理员不能禁言其他管理员，只有群主可以禁言管理员");
        }
        
        // 检查被禁言者是否是群成员
        List<User> participants = participantMapper.findParticipantsByConversationId(chatGroup.getConversationId());
        boolean isMember = participants.stream().anyMatch(p -> p.getId().equals(userId));
        if (!isMember) {
            throw new RuntimeException("该用户不是群成员");
        }
        
        // 创建禁言记录
        GroupMute groupMute = new GroupMute();
        groupMute.setGroupId(groupId);
        groupMute.setUserId(userId);
        groupMute.setMutedBy(operatorId);
        groupMute.setMuteUntil(muteUntil);
        
        groupMuteMapper.insert(groupMute);
        
        // 获取用户信息
        User user = userMapper.findById(userId);
        User operator = userMapper.findById(operatorId);
        
        groupMute.setUser(user);
        groupMute.setOperator(operator);
        
        // 创建通知
        Notification notification = new Notification();
        notification.setUserId(userId);
        notification.setType("GROUP_MUTED");
        notification.setGroupId(groupId);
        notification.setGroupName(chatGroup.getName());
        notification.setOperatorName(operator.getName());
        notification.setTitle("群聊禁言通知");
        notification.setContent("您在群聊 " + chatGroup.getName() + " 中被 " + operator.getName() + " 禁言");
        notification.setIsRead(false);
        notification.setCreatedAt(new Date());
        
        notificationService.addNotification(notification);
        
        return groupMute;
    }
    
    @Override
    public boolean unmuteGroupMember(Long groupId, Integer userId, Integer operatorId) {
        // 检查操作者权限
        ChatGroup chatGroup = chatGroupMapper.findById(groupId);
        if (chatGroup == null) {
            throw new RuntimeException("群组不存在");
        }
        
        boolean isOwner = chatGroup.getOwnerId().equals(operatorId);
        boolean isAdmin = groupAdminMapper.isGroupAdmin(groupId, operatorId);
        
        if (!isOwner && !isAdmin) {
            throw new RuntimeException("只有群主或管理员可以取消禁言");
        }
        
        // 取消禁言
        return groupMuteMapper.unmuteUser(groupId, userId) > 0;
    }
    
    @Override
    @Transactional
    public GroupMute muteGroup(Long groupId, Integer operatorId, Date muteUntil) {
        // 检查操作者权限
        ChatGroup chatGroup = chatGroupMapper.findById(groupId);
        if (chatGroup == null) {
            throw new RuntimeException("群组不存在");
        }
        
        boolean isOwner = chatGroup.getOwnerId().equals(operatorId);
        boolean isAdmin = groupAdminMapper.isGroupAdmin(groupId, operatorId);
        
        if (!isOwner && !isAdmin) {
            throw new RuntimeException("只有群主或管理员可以设置全群禁言");
        }
        
        // 创建全群禁言记录
        GroupMute groupMute = new GroupMute();
        groupMute.setGroupId(groupId);
        groupMute.setUserId(null); // null表示全群禁言
        groupMute.setMutedBy(operatorId);
        groupMute.setMuteUntil(muteUntil);
        
        groupMuteMapper.insert(groupMute);
        
        // 获取操作者信息
        User operator = userMapper.findById(operatorId);
        groupMute.setOperator(operator);
        
        return groupMute;
    }
    
    @Override
    public boolean unmuteGroup(Long groupId, Integer operatorId) {
        // 检查操作者权限
        ChatGroup chatGroup = chatGroupMapper.findById(groupId);
        if (chatGroup == null) {
            throw new RuntimeException("群组不存在");
        }
        
        boolean isOwner = chatGroup.getOwnerId().equals(operatorId);
        boolean isAdmin = groupAdminMapper.isGroupAdmin(groupId, operatorId);
        
        if (!isOwner && !isAdmin) {
            throw new RuntimeException("只有群主或管理员可以取消全群禁言");
        }
        
        // 取消全群禁言
        return groupMuteMapper.unmuteGroup(groupId) > 0;
    }
    
    @Override
    public boolean isUserMuted(Long groupId, Integer userId) {
        return groupMuteMapper.isUserMuted(groupId, userId);
    }
    
    @Override
    public boolean isGroupMuted(Long groupId) {
        return groupMuteMapper.isGroupMuted(groupId);
    }
    
    @Override
    public List<Map<String, Object>> getGroupMembersWithRoles(Long groupId) {
        // 获取群组信息
        ChatGroup chatGroup = chatGroupMapper.findById(groupId);
        if (chatGroup == null) {
            throw new RuntimeException("群组不存在");
        }
        
        Long conversationId = chatGroupMapper.findConversationIdByGroupId(groupId);
        if (conversationId == null) {
             throw new RuntimeException("无法找到群组对应的会话");
        }

        // 获取群成员列表
        List<User> participants = participantMapper.findParticipantsByConversationId(conversationId);
        
        // 获取管理员ID列表
        List<Integer> adminIds = groupAdminMapper.findAdminIdsByGroupId(groupId);
        
        // 获取禁言列表
        List<GroupMute> mutes = groupMuteMapper.findActiveByGroupId(groupId);
        Set<Integer> mutedUserIds = new HashSet<>();
        for (GroupMute mute : mutes) {
            if (mute.getUserId() != null) {
                mutedUserIds.add(mute.getUserId());
            }
        }
        
        // 组装结果
        List<Map<String, Object>> result = new ArrayList<>();
        for (User user : participants) {
            Map<String, Object> memberInfo = new HashMap<>();
            memberInfo.put("user", user);
            
            // 设置角色
            String role = "member"; // 普通成员
            if (chatGroup.getOwnerId().equals(user.getId())) {
                role = "owner"; // 群主
            } else if (adminIds.contains(user.getId())) {
                role = "admin"; // 管理员
            }
            memberInfo.put("role", role);
            
            // 设置禁言状态
            boolean isMuted = mutedUserIds.contains(user.getId());
            memberInfo.put("muted", isMuted);
            
            result.add(memberInfo);
        }
        
        return result;
    }
    
    @Override
    @Transactional
    public void disbandGroup(Long groupId, Integer operatorId) {
        // 1. 验证操作者是否是群主
        ChatGroup chatGroup = chatGroupMapper.findById(groupId);
        if (chatGroup == null) {
            throw new RuntimeException("群组不存在");
        }
        if (!chatGroup.getOwnerId().equals(operatorId)) {
            throw new RuntimeException("只有群主才能解散群聊");
        }

        Long conversationId = chatGroup.getConversationId();

        // 获取群主信息
        User owner = userMapper.findById(operatorId);
        String ownerName = owner != null ? owner.getName() : "未知用户";

        // 获取所有群成员
        List<User> members = participantMapper.findParticipantsByConversationId(conversationId);

        // 2. 删除群相关的所有记录（顺序很重要，避免外键约束问题）
        messageMapper.deleteByConversationId(conversationId);
        groupMuteMapper.deleteByGroupId(groupId);
        groupAdminMapper.deleteByGroupId(groupId);
        chatGroupMapper.deleteById(groupId);
        participantMapper.deleteByConversationId(conversationId);
        conversationMapper.deleteById(conversationId);

        // 3. 向所有群成员发送WebSocket消息并创建通知
        for (User member : members) {
            try {
                // 发送WebSocket消息
                ChatMessage message = new ChatMessage();
                message.setType("GROUP_DISBANDED");
                message.setGroupId(groupId);
                message.setGroupName(chatGroup.getName());
                message.setOwnerName(ownerName);
                message.setIsOwner(member.getId().equals(operatorId));
                message.setCreatedAt(new Date());

                chatWebSocketHandler.sendMessageToUser(member.getId(), message);
                
                // 创建通知记录
                Notification notification = new Notification();
                notification.setUserId(member.getId());
                notification.setType("GROUP_DISBANDED");
                notification.setGroupId(groupId);
                notification.setGroupName(chatGroup.getName());
                notification.setOperatorName(ownerName);
                notification.setIsOwner(member.getId().equals(operatorId));
                notification.setIsRead(false);
                notification.setCreatedAt(new Date());
                
                // 设置通知标题和内容
                if (member.getId().equals(operatorId)) {
                    notification.setTitle("群聊解散通知");
                    notification.setContent("您已解散群聊 \"" + chatGroup.getName() + "\"");
                } else {
                    notification.setTitle("群聊解散通知");
                    notification.setContent("群聊 \"" + chatGroup.getName() + "\" 已被群主 " + ownerName + " 解散");
                }
                
                // 保存通知
                notificationService.addNotification(notification);
            } catch (Exception e) {
                // 记录错误但不中断流程
                System.out.println("向用户" + member.getId() + "发送群解散消息失败: " + e.getMessage());
            }
        }
    }
} 